package com.zmc.lostfound.gateway.config;

import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.exception.NotPermissionException;
import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.http.HttpStatus;
import com.zmc.lostfound.common.constant.AuthConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author zmc
 * @description [Sa-Token 权限认证] 配置类
 */
@Slf4j
@Configuration
public class SaTokenConfigure {

    /**
     * 注册Sa-Token全局过滤器
     *
     * @return SaReactorFilter
     */
    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 拦截全部path
                .addInclude("/**")
                // 开放地址
                .addExclude(
                        "/api/auth/user/sendSmsCaptcha",
                        "/api/auth/user/checkPhoneCaptcha",
                        "/api/auth/user/updatePasswordByCaptcha",
                        "/api/auth/user/phoneCaptchaRegister",
                        "/api/auth/user/phoneCaptchaLogin",
                        "/api/auth/user/phonePasswordLogin",
                        "/api/auth/user/isLogin",
                        "/api/**/favicon.ico",
                        "/api/**/swagger-resources/**",
                        "/api/**/webjars/**",
                        "/api/**/v2/**",
                        "/api/**/doc.html/**",
                        "/favicon.ico")
                // 鉴权方法：每次访问进入
                .setAuth(obj -> {
                    // 登录校验 -- 拦截所有路由
                    SaRouter.match("/**").check(r -> StpUtil.checkLogin());

                    // 角色校验 -- 拦截所有路由
                    // 1.如果请求 角色CRUD、权限CRUD、给用户分配角色 的接口，只有超级管理员可以放行
                    SaRouter.match("/api/auth/role/**",
                            "/api/auth/permission/**",
                            "/api/auth/userRole/**",
                            "/api/auth/rolePermission/**")
                            .notMatch("/**/query/**")
                            .check(r -> StpUtil.checkRole(AuthConstant.RoleEnum.SUPER_ADMIN.getCode()))
                            .stop();

                    // 2.如果请求 用户、物品类型、公告、功能模块、用户反馈的敏感CRUD，只有管理员、超级管理员可以放行
                    SaRouter.match("/api/auth/user/insertUserWithAdmin",
                            "/api/auth/user/updateUserWithAdmin",
                            "/api/auth/user/kickout/{userId}",
                            "/api/auth/user/disable",
                            "/api/auth/user/untieDisable",
                            "/api/post/itemType/**",
                            "/api/system/notice/**",
                            "/api/system/function/**",
                            "/api/system/feedback/updateFeedback",
                            "/api/system/feedback/deleteBatchByIds",
                            "/api/system/feedback/deleteBatchByFunctionId/{functionId}",
                            "/api/system/feedback/deleteBatchByFunctionId/{functionId}",
                            "/api/system/feedback/delete/{userId}/and/{functionId}")
                            .notMatch("/**/query/**")
                            .check(r -> StpUtil.checkRoleOr(AuthConstant.RoleEnum.ADMIN.getCode(), AuthConstant.RoleEnum.SUPER_ADMIN.getCode()))
                            .stop();

                    // 3.如果请求 帖子审核、举报信息的敏感CRUD，只有审核员、管理员、超级管理员可以放行
                    SaRouter.match("/api/post/postReview/**", "/api/post/postReport/**")
                            .notMatch("/**/query/**", "/api/post/postReport/insertPostReport")
                            .check(r -> StpUtil.checkRoleOr(AuthConstant.RoleEnum.AUDITOR.getCode(),
                                    AuthConstant.RoleEnum.ADMIN.getCode(),
                                    AuthConstant.RoleEnum.SUPER_ADMIN.getCode()))
                            .stop();
                })
                // 异常处理方法：每次setAuth函数出现异常时进入
                .setError(e -> {
                    log.error("【Sa-Token】setAuth函数出现异常: " + e.getMessage());
                    if (e instanceof NotLoginException) {
                        return new SaResult(HttpStatus.HTTP_UNAUTHORIZED, "登录信息已过期，请重新登录", e.getMessage());
                    }
                    if (e instanceof NotRoleException || e instanceof NotPermissionException) {
                        return new SaResult(HttpStatus.HTTP_FORBIDDEN, "无操作权限", e.getMessage());
                    }
                    return SaResult.error(e.getMessage());
                });
    }

}


